package com.yuandian.customer.perception.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.api.customer_perception.po.BusinessPerformanceParams;
import com.yuandian.api.customer_perception.po.InterfacePerformanceParams;
import com.yuandian.api.customer_perception.po.WeekdayParams;
import com.yuandian.api.customer_perception.vo.*;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.customer.perception.controller.InterfacePerformanceController;
import com.yuandian.customer.perception.mapper.InterfacePerformanceMapper;
import com.yuandian.customer.perception.service.InterfacePerformanceService;
import com.yuandian.enums.TableNameEnum;
import com.yuandian.utils.DateTool;
import com.yuandian.utils.PageDataInfo;
import com.yuandian.utils.StringUtils;
import com.yuandian.utils.YDateUtil;
import com.yuandian.utils.poi.ExcelTitleUtils;
import com.yuandian.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 说明：接口性能优化service实现类
 */
@Slf4j
@Service
public class InterfacePerformanceServiceImpl implements InterfacePerformanceService {


	@Autowired
	private InterfacePerformanceMapper interfacePerformanceMapper;

//	@Autowired
//	private IWeekdaysService weekdaysService;


	/**
	 * 查询具体用户列表
	 *
	 * @param params
	 * @return
	 */
	//@DS("khgzData")
	@Override
	public R querySpecificOperatorList(BusinessPerformanceParams params) {
		Page<SpecificUserInterfaceVo> page = new Page<>(params.getPageNum(), params.getPageSize());

		// 执行查询
		List<SpecificUserInterfaceVo> list = interfacePerformanceMapper.querySpecificOperatorList(page, params);
		return R.ok(new PageDataInfo(page, list));
	}

	/**
	 * 查询用户操作轨迹趋势图
	 *
	 * @param params
	 * @return
	 */
	//@DS("khgzData")
	@Override
	public R queryOperatorTrajectoryTrend(BusinessPerformanceParams params) {


		params.setTableName(TableNameEnum.BUSI_STEP_URL_STAT.getName());
		List<OperatorTrajectoryVisitCountTrendVo> visitCountList = interfacePerformanceMapper.queryOperatorTrajectoryTrend(params);
		// 查询ES 步骤二表获取接口对应业务的办理时长
		List<OperatorTrajectoryDealTimeTrendVo> dealTimeList = new ArrayList<>();

		Map<String, Object> map = getDealTimeList(params);
		dealTimeList = (List<OperatorTrajectoryDealTimeTrendVo>) map.get("data");

		if (dealTimeList != null && dealTimeList.size() > 0) {
			dealTimeList.sort(Comparator.comparing(OperatorTrajectoryDealTimeTrendVo::getLabelTime, Comparator.naturalOrder()));
		}

		OperatorTrajectoryTrendVo resVo = new OperatorTrajectoryTrendVo();
		resVo.setDealTimeList(dealTimeList);
		resVo.setVisitCountList(visitCountList);
		return R.ok(resVo);
	}

	/**
	 * 用户轨迹趋势图-获取指定用户标识指定时间指定URL的办理时长
	 *
	 * @param params
	 * @return
	 */
	private Map<String, Object> getDealTimeList(BusinessPerformanceParams params) {
		List<OperatorTrajectoryDealTimeTrendVo> resList = new ArrayList<>();

		params.setTableName(TableNameEnum.BUSINESS_STEP2.getName());
		String[] fields = {"systemId", "systemName", "businessCode", "businessName", "stepName", "dealTime", "endTime"};
		// 2.2、设置查询条件
		List<OperatorTrajectoryDealTimeTrendVo> list = interfacePerformanceMapper.getDealTimeList(params);

//		List<Map<String, Object>> sourceMapList = ElasticsearchUtils.searchAllList(queryTableNames, fields, boolQuery);

		HashMap<String, Object> map = new HashMap<>();
		map.put("data", resList);
//		map.put("prompt", prompt);
		return map;
	}


	/**
	 * 查询接口性能变化趋势
	 *
	 * @param params
	 * @return
	 */
	//@DS("khgzData")
	@Override
	public R queryImplementPerformanceTrend(BusinessPerformanceParams params) {
		// 获取开始和结束时间
		params.setTableName(TableNameEnum.BUSI_STEP_URL_STAT.getName());

		List<ImplementPerformanceTrendVo> list = interfacePerformanceMapper.queryImplementPerformanceTrend(params);
		// 获取坐标轴
		List<String> axis = new ArrayList<>();
		DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime startDate = LocalDateTime.parse(params.getStartTime(), dayFormatter).withHour(0).withMinute(0).withSecond(0);
		LocalDateTime endDate = LocalDateTime.parse(params.getEndTime(), dayFormatter).withHour(0).withMinute(0).withSecond(0);

		while (startDate.isBefore(endDate)) {
			axis.add(startDate.format(dayFormatter));
			startDate = startDate.plusDays(1);
		}

		// 获取配置库节假日和工作日列表
		WeekdayParams weekdayParams = new WeekdayParams();
//		List<Weekday> dayList = weekdaysService.queryNoPageWeekday(weekdayParams);
//		Map<String, Weekday> dayListCollect = dayList.stream().collect(Collectors.toMap(Weekday::getDay, v -> v, (k1, k2) -> k1));
		Map<String, ImplementPerformanceTrendVo> listCollect = list.stream().collect(Collectors.toMap(ImplementPerformanceTrendVo::getLabelTime, v -> v, (k1, k2) -> k1));

		// 进行数据回填
		List<ImplementPerformanceTrendVo> resList = new ArrayList<>();
		for (String s : axis) {
			ImplementPerformanceTrendVo vo = new ImplementPerformanceTrendVo();
			if (listCollect.containsKey(s)) {
				vo.setVisitCount(listCollect.get(s).getVisitCount());
				vo.setAvgDealTime(listCollect.get(s).getAvgDealTime());
			} else {
				vo.setVisitCount(0);
				vo.setAvgDealTime(0d);
			}

//			Weekday day = dayListCollect.get(s.substring(0, 10));
//			if (day != null && day.getType() == 2) {
//				vo.setIsWeekdays(2);
//			} else {
//				vo.setIsWeekdays(1);
//			}

			vo.setLabelTime(s.substring(0, 10));
			resList.add(vo);
		}
		return R.ok(resList);
	}


	private String getBeforeTimeStr(String endTime, int showTime) {

		String beforeTime = DateTool.yyyy_MM_dd_00_00_00(DateTool.getBeforeDate(
				DateTool.yyyy_MM_dd_HH_mm_ss(endTime), showTime));

		return beforeTime;
	}


	/**
	 * 查询接口URL运行概况总览
	 *
	 * @param params
	 * @return R()
	 */
	@Override
	//@DS("khgzData")
	public Map<String, Object> queryInterfaceURLPerformance(InterfacePerformanceParams params) {
		//创建分页对象,并设置页面大小和页数
		Page<InterfaceURLPerformanceVo> page = new Page<>(params.getPageNum(), params.getPageSize());

		//通过mybatis查询全部url数据
		List<InterfaceURLPerformanceVo> interfaceURLPerformanceVos = new ArrayList<>();

		// 当接口状态不为空置时
		if (params.getInterfaceState() == null || params.getInterfaceState() != 2) {
			//查询全部速度区间
			List<SpeedRangeVo> speedRangeVos = queryAllSpeedRange(params);
			//需要的端点集合
			List<Integer> rangePointList = new ArrayList<>();
			//如果speedRangeList不为空则去除没有选中的区间,为空则展示全部区间
			if (params.getSpeedRangeList() != null && params.getSpeedRangeList().size() > 0) {
				List<String> speedRangeList = params.getSpeedRangeList();
				for (SpeedRangeVo speedRangeVo : speedRangeVos) {
					if (speedRangeList.contains(speedRangeVo.getRemarks())) {
						rangePointList.add(speedRangeVo.getRangeLeft());
						rangePointList.add(speedRangeVo.getRangeRight());
					}
				}
			} else {
				for (SpeedRangeVo speedRangeVo : speedRangeVos) {
					rangePointList.add(speedRangeVo.getRangeLeft());
					rangePointList.add(speedRangeVo.getRangeRight());
				}
			}
			params.setRangePointList(rangePointList);

			try {
				interfaceURLPerformanceVos.addAll(interfacePerformanceMapper.queryInterfaceURLPerformance(params));
			} catch (Exception e) {
				log.error(e.getMessage());
			}
			//设置保留两位小数
			DecimalFormat df = new DecimalFormat("0.00");
			for (InterfaceURLPerformanceVo interfaceURLPerformanceVo : interfaceURLPerformanceVos) {
				//回填avgDealTimeStr和healthRateStr和请求大小响应大小等
				interfaceURLPerformanceVo.setAvgRequestBytesStr(InterfacePerformanceController.getData(interfaceURLPerformanceVo.getAvgRequestBytes()));
				interfaceURLPerformanceVo.setAvgResponseBytesStr(InterfacePerformanceController.getData(interfaceURLPerformanceVo.getAvgResponseBytes()));
				interfaceURLPerformanceVo.setAvgDealTimeStr(DateTool.getMinSecond(interfaceURLPerformanceVo.getAvgDealTime() / 1000));
				interfaceURLPerformanceVo.setHealthRateStr(df.format(interfaceURLPerformanceVo.getHealthRate()) + "%");
				//回填speedRange
				for (SpeedRangeVo speedRangeVo : speedRangeVos) {
					if (interfaceURLPerformanceVo.getAvgDealTime() / 1000000 >= speedRangeVo.getRangeLeft() && interfaceURLPerformanceVo.getAvgDealTime() / 1000000 < speedRangeVo.getRangeRight()) {
						interfaceURLPerformanceVo.setSpeedRange(speedRangeVo.getRemarks());
					}
				}
			}
		}
		if (params.getInterfaceState() != null && params.getInterfaceState() != 1 && (params.getSpeedRangeList().size() == 0 || params.getSpeedRangeList().contains("小于2秒"))) {
			List<InterfaceHealThRateTopVo> interfaceFreeVos = queryInterfaceFreeState(params);
			for (InterfaceHealThRateTopVo interfaceFreeVo : interfaceFreeVos) {
				InterfaceURLPerformanceVo interfaceURLPerformanceVo = new InterfaceURLPerformanceVo();
				interfaceURLPerformanceVo.setAlarmCount(0L);
				interfaceURLPerformanceVo.setAvgDealTime(0D);
				interfaceURLPerformanceVo.setAvgDealTimeStr("0.00毫秒");
				interfaceURLPerformanceVo.setAvgRequestBytes(0L);
				interfaceURLPerformanceVo.setAvgRequestBytesStr("0B");
				interfaceURLPerformanceVo.setAvgResponseBytes(0L);
				interfaceURLPerformanceVo.setAvgResponseBytesStr("0B");
				interfaceURLPerformanceVo.setHealthRate(0d);
				interfaceURLPerformanceVo.setHealthRateStr("0%");
				interfaceURLPerformanceVo.setSpeedRange("小于2秒");
				interfaceURLPerformanceVo.setUrlApi(interfaceFreeVo.getUrlApi());
				interfaceURLPerformanceVo.setVisitCount(0L);
				interfaceURLPerformanceVo.setUserNumber(0);
				interfaceURLPerformanceVo.setSystemName(interfaceFreeVo.getSystemName());
				interfaceURLPerformanceVos.add(interfaceURLPerformanceVo);
			}
		}

		//需求880变更,只能手动分页
		return manualPage(params, interfaceURLPerformanceVos);
	}

	public Map<String, Object> manualPage(InterfacePerformanceParams params, List<InterfaceURLPerformanceVo> interfaceURLPerformanceVos) {
		int total = interfaceURLPerformanceVos.size();
		int fromIndex = (Integer.valueOf((int) params.getPageNum()) - 1) * Integer.valueOf((int) params.getPageSize());
		int toIndex = fromIndex + Integer.valueOf((int) params.getPageSize());
		if (toIndex > total) {
			toIndex = total;
		}
		HashMap<String, Object> map = new HashMap<>(2);
		if (fromIndex <= total) {
			List<InterfaceURLPerformanceVo> interfaceHealThRateTopVos = interfaceURLPerformanceVos.subList(fromIndex, toIndex);

			map.put("data", interfaceHealThRateTopVos);
			map.put("total", total);

		}
		return map;
	}

	/**
	 * 下载接口URL运行概况总览
	 *
	 * @param params @return
	 */
	@Override
	//@DS("khgzData")
	public void exportInterfaceURLPerformance(InterfacePerformanceParams params, HttpServletResponse response) throws IOException {
		//取消分页
		params.setPageNum(1);
		params.setPageSize(1000000000L);
		//获取数据
		List<InterfaceURLPerformanceVo> interfaceURLPerformanceVos = new ArrayList<>();
		try {
			interfaceURLPerformanceVos = (List<InterfaceURLPerformanceVo>) queryInterfaceURLPerformance(params).get("data");
		} catch (Exception e) {
			log.error("所选时间表不存在!但表格需要正常导出.");
		}
		//设置excel下载序号
		int index = 1;
		for (InterfaceURLPerformanceVo interfaceURLPerformanceVo : interfaceURLPerformanceVos) {
			interfaceURLPerformanceVo.setId(index++);
		}
		//excel主标题,如"XX系统XX业务接口URL运行概况总览列表_开始时间~结束时间"
		String title = "接口URL运行概况总览列表";
		List<String> titleParams = new ArrayList<>();
		titleParams.add(title);
		titleParams.add(params.getSystemName() == null ? "全系统" : params.getSystemName());
		titleParams.add(params.getBusinessName());
		String formTitleName = ExcelTitleUtils.formTitleName(titleParams, params.getStartTime(), params.getEndTime());
		//列标题
		List<List<String>> headList = new ArrayList<>();
		List<String> titleList = Arrays.asList("序号", "系统名称", "接口URL", "访问量", "告警访问量", "平均处理时长", "速度区间分布", "平均请求大小", "平均响应大小", "健康度", "用户数");
		//写定一个不会变的变量,防止lambda表达式报错
		//将标题名和列名写入
		titleList.forEach(s -> {
			List<String> childHeadList = new ArrayList<>();
			childHeadList.add(formTitleName);
			childHeadList.add(s);
			headList.add(childHeadList);
		});
		ExcelUtil.writeExcel(InterfaceURLPerformanceVo.class, formTitleName, title, interfaceURLPerformanceVos, headList, response);
	}

	/**
	 * 查询关联业务
	 *
	 * @param params(businessCode,startTime,endTime)
	 * @return PageDataInfo(InterfaceURLPerformanceVo)
	 */
	@Override
	//@DS("khgzData")
	public List<RelatedBusinessVo> queryRelatedBusiness(InterfacePerformanceParams params) {
		//保留原tableName
		List<String> businessCodes = interfacePerformanceMapper.queryBusinessCodes(params);
		if (businessCodes.size() == 0) {
			return new ArrayList<>();
		}
		//回填businessCodes和原表名
		params.setBusinessCodes(businessCodes);

		List<RelatedBusinessVo> relatedBusinessVos = interfacePerformanceMapper.queryRelatedBusiness(params);
		//回填speedRange
		List<SpeedRangeVo> speedRangeVos = queryAllSpeedRange(params);
		for (RelatedBusinessVo relatedBusinessVo : relatedBusinessVos) {
			for (SpeedRangeVo speedRangeVo : speedRangeVos) {
				if (relatedBusinessVo.getAvgDealTime() / 1000000 >= speedRangeVo.getRangeLeft() && relatedBusinessVo.getAvgDealTime() / 1000000 < speedRangeVo.getRangeRight()) {
					relatedBusinessVo.setSpeedRange(speedRangeVo.getRemarks());
				}
			}
		}
		return relatedBusinessVos;
	}

	/**
	 * 查询接口健康度Top10
	 *
	 * @param params
	 * @return List(interfaceHealThRateTopVo)
	 */
	@Override
	//@DS("khgzData")
	public List<InterfaceHealThRateTopVo> queryInterfaceHealthRateTop10(InterfacePerformanceParams params) {
		List<InterfaceHealThRateTopVo> interfaceHealThRateTopVos = new ArrayList<>();
		// 当接口状态不为空置时
		if (params.getInterfaceState() == null || params.getInterfaceState() != 2) {
			//回填排序方式,默认按照健康度升序排序
			if (params.getOrderByColumn() == null || params.getOrderByColumn() == "") {
				params.setOrderByColumn("healthRate");
				params.setIsAsc("ASC");
			} else {
				//访问量按降序排序,平均处理时长按降序排序
				switch (params.getOrderByColumn()) {
					case "healthRate":
						params.setIsAsc("ASC");
						break;
					case "visitCount":
					case "avgDealTime":
						params.setIsAsc("DESC");
						break;
				}
			}
			interfaceHealThRateTopVos.addAll(interfacePerformanceMapper.queryInterfaceHealthRateTop10(params));
		}
		// 当接口状态不为可用时
		if (params.getInterfaceState() != null && params.getInterfaceState() != 1) {
			if (interfaceHealThRateTopVos.size() < 10) {
				//查询的是配置库表
				List<InterfaceHealThRateTopVo> interfaceFreeVos = queryInterfaceFreeState(params);
				List<InterfaceHealThRateTopVo> healThRateTopVos = interfaceFreeVos.stream().filter(Objects::nonNull).collect(Collectors.toList());
				for (InterfaceHealThRateTopVo healThRateTopVo : healThRateTopVos) {
					if (interfaceHealThRateTopVos.size() == 10) {
						break;
					}
					healThRateTopVo.setAlarmCount(0L);
					healThRateTopVo.setAvgDealTime(0D);
					healThRateTopVo.setHealthRate(0D);
					healThRateTopVo.setVisitCount(0L);
					interfaceHealThRateTopVos.add(healThRateTopVo);
				}
			}
		}
		return interfaceHealThRateTopVos;
	}


	public List<InterfaceHealThRateTopVo> queryInterfaceFreeState(InterfacePerformanceParams params) {
		List<InterfaceHealThRateTopVo> interfaceHealThRateTopVos = interfacePerformanceMapper.queryInterfaceFreeState(params);
		Iterator<InterfaceHealThRateTopVo> iterator = interfaceHealThRateTopVos.iterator();
		List<String> usingInterface = interfacePerformanceMapper.queryUseringInterfaceByTime(params);
		while (iterator.hasNext()) {
			InterfaceHealThRateTopVo next = iterator.next();
			if (usingInterface.contains(next.getUrlApi())) {
				iterator.remove();
			}
		}
		return interfaceHealThRateTopVos;
	}


	/**
	 * 用户操作轨迹列表
	 *
	 * @param params
	 * @return
	 */
	@Override
	public PageDataInfo queryUserOperationTrajectory(InterfacePerformanceParams params) {
		//用户操作轨迹对象集合
		List<UserOperationTrajectoryVo> userOperationTrajectoryVos = new ArrayList<>();
		//获取字段名
		String[] fields = {"userIdentify", "systemName", "businessName", "requestBytes",
				"responseBytes", "startTime", "endTime", "dealState", "dealTime"};
		params.setTableName(TableNameEnum.BUSINESS_STEP2.getName());
		IPage<UserOperationTrajectoryVo> page = new Page<>(params.getPageNum(), params.getPageSize());
		Page<UserOperationTrajectoryVo> resPage = interfacePerformanceMapper.queryUserOperationTrajectory(page, params);

		return new PageDataInfo(resPage);
	}

	/**
	 * 下载用户操作轨迹列表
	 *
	 * @param params
	 * @param response
	 * @return
	 */
	@Override
	public void exportUserOperationTrajectory(InterfacePerformanceParams params, HttpServletResponse response) throws IOException {
		//取消分页
		params.setPageNum(1);
		params.setPageSize(1000000L);
		//获取数据
		List<UserOperationTrajectoryVo> userOperationTrajectoryVos = new ArrayList<>();
		try {
			userOperationTrajectoryVos = (List<UserOperationTrajectoryVo>) queryUserOperationTrajectory(params).getData();
		} catch (Exception e) {
			log.error("所选时间表不存在!但表格需要正常导出.");
		}
		//设置excel下载序号
		int index = 1;
		for (UserOperationTrajectoryVo userOperationTrajectoryVo : userOperationTrajectoryVos) {
			userOperationTrajectoryVo.setId(index++);
		}
		//excel主标题,如"XX用户操作轨迹列表_开始时间~结束时间"
		String formTitleName = params.getOperatorId() + "用户操作轨迹列表[" + params.getStartTime() + "~" + params.getEndTime() + "]";
		//列标题
		List<List<String>> headList = new ArrayList<>();
		List<String> titleList = Arrays.asList("序号", "用户标识", "系统名称", "业务名称", "请求大小", "响应大小", "处理时长", "开始时间", "结束时间", "业务状态");
		//将标题名和列名写入
		titleList.forEach(s -> {
			List<String> childHeadList = new ArrayList<>();
			childHeadList.add(formTitleName);
			childHeadList.add(s);
			headList.add(childHeadList);
		});
		ExcelUtil.writeExcel(UserOperationTrajectoryVo.class, formTitleName, "用户操作轨迹列表", userOperationTrajectoryVos, headList, response);
	}

	/**
	 * 查询全部接口url
	 *
	 * @param params
	 * @return List<String>
	 */
	//@DS("khgzData")
	@Override
	public List<String> queryAllUrl(InterfacePerformanceParams params) {
		ArrayList<String> urlApis = new ArrayList<>();
		// 当接口状态不为空置时
		if (params.getInterfaceState() == null || params.getInterfaceState() != 2) {
			urlApis.addAll(interfacePerformanceMapper.queryAllUrl(params));
		}
		// 当接口状态不为在用时
		if (params.getInterfaceState() != null && params.getInterfaceState() != 1) {
			List<InterfaceHealThRateTopVo> interfaceFreeVos = queryInterfaceFreeState(params);
			urlApis.addAll(interfaceFreeVos.stream().map(InterfaceHealThRateTopVo::getUrlApi).collect(Collectors.toList()));
		}

		return urlApis;
	}

	/**
	 * 查询全部速度区间
	 *
	 * @param params@return List<String>
	 */
	@Override
	public List<SpeedRangeVo> queryAllSpeedRange(InterfacePerformanceParams params) {
		List<SpeedRangeVo> speedRangeVos = new ArrayList<>();//interfacePerformanceMapper.queryAllSpeedRange();//todo 远程调用
		SpeedRangeVo speedRangeVo = new SpeedRangeVo(0,2, "小于2秒");
		SpeedRangeVo speedRangeVo1 = new SpeedRangeVo(2,5, "2秒~5秒");
		SpeedRangeVo speedRangeVo2 = new SpeedRangeVo(5,1000, "大于5秒");
		speedRangeVos.add(speedRangeVo);
		speedRangeVos.add(speedRangeVo1);
		speedRangeVos.add(speedRangeVo2);
		return speedRangeVos;
	}
}
